﻿#region using statements

using System;
using Microsoft.Xna.Framework;

#endregion

namespace XNAGameEngine.Alarms
{
    /// <summary>
    /// This is the actual alarm object. Once the timer expires, it will send the message back to its parent
    /// </summary>
    public class AlarmObject
    {
        #region delegates

        /// <summary>
        /// Delegate for alarm event throwing
        /// </summary>
        /// <param name="alarmMessage">the string message sent from the alarm</param>
        private delegate void AlarmEventHandler(string alarmMessage);

        #endregion

        #region events

        /// <summary>
        /// Event object that stores the reference to the callback function of the parent
        /// </summary>
        private event AlarmEventHandler ThrowAlarmEvent;

        #endregion

        #region local objects

        /// <summary>
        /// the message sent by the alarm back to the parent object
        /// </summary>
        private readonly string _message;

        /// <summary>
        /// represents the time left until this alarm activates
        /// </summary>
        private double _timer;

        #endregion

        #region properties

        /// <summary>
        /// Gets the time remaining until this alarm is triggered
        /// </summary>
        public double _TimeRemaning
        {
            get { return _timer; }
        }

        /// <summary>
        /// Returns the message stored in the alarm
        /// </summary>
        public string _GetMessage
        {
            get { return _message; }
        }

        #endregion

        #region constructors

        /// <summary>
        /// Constructor sets the timer, message and parent
        /// </summary>
        /// <param name="parent">the object that will receive the alarm callback</param>
        /// <param name="alarmTime">the duration of the alarm</param>
        /// <param name="alarmMessage">the message to pass to the callback method</param>
        public AlarmObject(object parent, double alarmTime, string alarmMessage)
        {
            if (!(parent is IAlarmListener))
                throw new SystemException(
                    "object listener passed in does not implement IAlarmSystemCallbacks");

            ThrowAlarmEvent += (parent as IAlarmListener).OnAlarmEvent;
            _timer = alarmTime * 1000;
            _message = alarmMessage;
        }

        #endregion

        #region local methods

        /// <summary>
        /// <para>Update the alarm time. If the timer reaches 0 then throw the callback event
        /// and return true so that the alarm system will remove the alarm</para>
        /// <para>If you override this method, be sure to return true whenever you wish for the
        /// alarm to be removed from the alarm system. Otherwise the alarm will always exist.</para>
        /// </summary>
        /// <param name="gameTime">the game time object</param>
        /// <returns>true if the alarm should be removed from the alarm system, false otherwise</returns>
        public virtual bool Update(GameTime gameTime)
        {
            _timer -= gameTime.ElapsedGameTime.Milliseconds;
            if (_timer <= 0)
            {
                Action();
                return true;
            }
            return false;
        }

        /// <summary>
        /// <para>The action to take once the alarm timer reaches 0</para>
        /// </summary>
        public virtual void Action()
        {
            ThrowAlarmEvent(_message);
        }

        #endregion
    }
}